home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / emacs / src / fns.c < prev    next >
C/C++ Source or Header  |  1992-10-16  |  35KB  |  1,410 lines

  1. /* Random utility Lisp functions.
  2.    Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22.  
  23. #ifdef LOAD_AVE_TYPE
  24. #ifdef BSD
  25. /* It appears param.h defines BSD and BSD4_3 in 4.3
  26.    and is not considerate enough to avoid bombing out
  27.    if they are already defined.  */
  28. #undef BSD
  29. #ifdef BSD4_3
  30. #undef BSD4_3
  31. #define XBSD4_3 /* XBSD4_3 says BSD4_3 is supposed to be defined.  */
  32. #endif
  33. #include <sys/param.h>
  34. /* Now if BSD or BSD4_3 was defined and is no longer,
  35.    define it again.  */
  36. #ifndef BSD
  37. #define BSD
  38. #endif
  39. #ifdef XBSD4_3
  40. #ifndef BSD4_3
  41. #define BSD4_3
  42. #endif
  43. #endif /* XBSD4_3 */
  44. #endif /* BSD */
  45. #ifndef VMS
  46. #ifndef NLIST_STRUCT
  47. #include <a.out.h> 
  48. #else /* NLIST_STRUCT */
  49. #include <nlist.h>
  50. #endif /* NLIST_STRUCT */
  51. #endif /* not VMS */
  52. #endif /* LOAD_AVE_TYPE */
  53.  
  54. #ifdef DGUX
  55. #include <sys/dg_sys_info.h>  /* for load average info - DJB */
  56. #endif
  57.  
  58. /* Note on some machines this defines `vector' as a typedef,
  59.    so make sure we don't use that name in this file.  */
  60. #undef vector
  61. #define vector *****
  62.  
  63. #ifdef NULL
  64. #undef NULL
  65. #endif
  66. #include "lisp.h"
  67. #include "commands.h"
  68.  
  69. #ifdef lint
  70. #include "buffer.h"
  71. #endif /* lint */
  72.  
  73. Lisp_Object Qstring_lessp;
  74.  
  75. DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
  76.   "Return the argument unchanged.")
  77.   (arg)
  78.      Lisp_Object arg;
  79. {
  80.   return arg;
  81. }
  82.  
  83. DEFUN ("random", Frandom, Srandom, 0, 1, 0,
  84.   "Return a pseudo-random number.\n\
  85. On most systems all integers representable in Lisp are equally likely.\n\
  86.   This is 24 bits' worth.\n\
  87. On some systems, absolute value of result never exceeds 2 to the 14.\n\
  88. If optional argument is supplied as  t,\n\
  89.  the random number seed is set based on the current time and pid.")
  90.   (arg)
  91.      Lisp_Object arg;
  92. {
  93.   extern long random ();
  94.   extern srandom ();
  95.   extern long time ();
  96.  
  97.   if (EQ (arg, Qt))
  98.     srandom (getpid () + time (0));
  99.   return make_number ((int) random ());
  100. }
  101.  
  102. /* Random data-structure functions */
  103.  
  104. DEFUN ("length", Flength, Slength, 1, 1, 0,
  105.   "Return the length of vector, list or string SEQUENCE.")
  106.   (obj)
  107.      register Lisp_Object obj;
  108. {
  109.   register Lisp_Object tail, val;
  110.   register int i;
  111.  
  112.  retry:
  113.   if (XTYPE (obj) == Lisp_Vector || XTYPE (obj) == Lisp_String)
  114.     return Farray_length (obj);
  115.   else if (CONSP (obj))
  116.     {
  117.       for (i = 0, tail = obj; !NULL(tail); i++)
  118.     {
  119.       QUIT;
  120.       tail = Fcdr (tail);
  121.     }
  122.  
  123.       XFASTINT (val) = i;
  124.       return val;
  125.     }
  126.   else if (NULL(obj))
  127.     {
  128.       XFASTINT (val) = 0;
  129.       return val;
  130.     }
  131.   else
  132.     {
  133.       obj = wrong_type_argument (Qsequencep, obj);
  134.       goto retry;
  135.     }
  136. }
  137.  
  138. DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
  139.   "T if two strings have identical contents.\n\
  140. Symbols are also allowed; their print names are used instead.")
  141.   (s1, s2)
  142.      register Lisp_Object s1, s2;
  143. {
  144.   if (XTYPE (s1) == Lisp_Symbol)
  145.     XSETSTRING (s1, XSYMBOL (s1)->name), XSETTYPE (s1, Lisp_String);
  146.   if (XTYPE (s2) == Lisp_Symbol)
  147.     XSETSTRING (s2, XSYMBOL (s2)->name), XSETTYPE (s2, Lisp_String);
  148.   CHECK_STRING (s1, 0);
  149.   CHECK_STRING (s2, 1);
  150.  
  151.   if (XSTRING (s1)->size != XSTRING (s2)->size ||
  152.       bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size))
  153.     return Qnil;
  154.   return Qt;
  155. }
  156.  
  157. DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
  158.   "T if first arg string is less than second in lexicographic order.\n\
  159. Symbols are also allowed; their print names are used instead.")
  160.   (s1, s2)
  161.      register Lisp_Object s1, s2;
  162. {
  163.   register int i;
  164.   register unsigned char *p1, *p2;
  165.   register int end;
  166.  
  167.   if (XTYPE (s1) == Lisp_Symbol)
  168.     XSETSTRING (s1, XSYMBOL (s1)->name), XSETTYPE (s1, Lisp_String);
  169.   if (XTYPE (s2) == Lisp_Symbol)
  170.     XSETSTRING (s2, XSYMBOL (s2)->name), XSETTYPE (s2, Lisp_String);
  171.   CHECK_STRING (s1, 0);
  172.   CHECK_STRING (s2, 1);
  173.  
  174.   p1 = XSTRING (s1)->data;
  175.   p2 = XSTRING (s2)->data;
  176.   end = XSTRING (s1)->size;
  177.   if (end > XSTRING (s2)->size)
  178.     end = XSTRING (s2)->size;
  179.  
  180.   for (i = 0; i < end; i++)
  181.     {
  182.       if (p1[i] != p2[i])
  183.     return p1[i] < p2[i] ? Qt : Qnil;
  184.     }
  185.   return i < XSTRING (s2)->size ? Qt : Qnil;
  186. }
  187.  
  188. static Lisp_Object concat ();
  189.  
  190. /* ARGSUSED */
  191. Lisp_Object
  192. concat2 (s1, s2)
  193.      Lisp_Object s1, s2;
  194. {
  195. #ifdef NO_ARG_ARRAY
  196.   Lisp_Object args[2];
  197.   args[0] = s1;
  198.   args[1] = s2;
  199.   return concat (2, args, Lisp_String, 0);
  200. #else
  201.   return concat (2, &s1, Lisp_String, 0);
  202. #endif /* NO_ARG_ARRAY */
  203. }
  204.  
  205. DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
  206.   "Concatenate arguments and make the result a list.\n\
  207. The result is a list whose elements are the elements of all the arguments.\n\
  208. Each argument may be a list, vector or string.")
  209.   (nargs, args)
  210.      int nargs;
  211.      Lisp_Object *args;
  212. {
  213.   return concat (nargs, args, Lisp_Cons, 1);
  214. }
  215.  
  216. DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
  217.   "Concatenate arguments and make the result a string.\n\
  218. The result is a string whose elements are the elements of all the arguments.\n\
  219. Each argument may be a string, a list of numbers, or a vector of numbers.")
  220.   (nargs, args)
  221.      int nargs;
  222.      Lisp_Object *args;
  223. {
  224.   return concat (nargs, args, Lisp_String, 0);
  225. }
  226.  
  227. DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
  228.   "Concatenate arguments and make the result a vector.\n\
  229. The result is a vector whose elements are the elements of all the arguments.\n\
  230. Each argument may be a list, vector or string.")
  231.   (nargs, args)
  232.      int nargs;
  233.      Lisp_Object *args;
  234. {
  235.   return concat (nargs, args, Lisp_Vector, 0);
  236. }
  237.  
  238. DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
  239.   "Return a copy of a list, vector or string.")
  240.   (arg)
  241.      Lisp_Object arg;
  242. {
  243.   if (NULL (arg)) return arg;
  244.   if (!CONSP (arg) && XTYPE (arg) != Lisp_Vector && XTYPE (arg) != Lisp_String)
  245.     arg = wrong_type_argument (Qsequencep, arg);
  246.   return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
  247. }
  248.  
  249. static Lisp_Object
  250. concat (nargs, args, target_type, last_special)
  251.      int nargs;
  252.      Lisp_Object *args;
  253.      enum Lisp_Type target_type;
  254.      int last_special;
  255. {
  256.   Lisp_Object val;
  257.   Lisp_Object len;
  258.   register Lisp_Object tail;
  259.   register Lisp_Object this;
  260.   int toindex;
  261.   register int leni;
  262.   register int argnum;
  263.   Lisp_Object last_tail;
  264.   Lisp_Object prev;
  265.  
  266.   /* In append, the last arg isn't treated like the others */
  267.   if (last_special && nargs > 0)
  268.     {
  269.       nargs--;
  270.       last_tail = args[nargs];
  271.     }
  272.   else
  273.     last_tail = Qnil;
  274.  
  275.   for (argnum = 0; argnum < nargs; argnum++)
  276.     {
  277.       this = args[argnum];
  278.       if (!(CONSP (this) || NULL (this)
  279.           || XTYPE (this) == Lisp_Vector || XTYPE (this) == Lisp_String))
  280.     {
  281.       if (XTYPE (this) == Lisp_Int)
  282.             args[argnum] = Fint_to_string (this);
  283.       else
  284.         args[argnum] = wrong_type_argument (Qsequencep, this);
  285.     }
  286.     }
  287.  
  288.   for (argnum = 0, leni = 0; argnum < nargs; argnum++)
  289.     {
  290.       this = args[argnum];
  291.       len = Flength (this);
  292.       leni += XFASTINT (len);
  293.     }
  294.  
  295.   XFASTINT (len) = leni;
  296.  
  297.   if (target_type == Lisp_Cons)
  298.     val = Fmake_list (len, Qnil);
  299.   else if (target_type == Lisp_Vector)
  300.     val = Fmake_vector (len, Qnil);
  301.   else
  302.     val = Fmake_string (len, len);
  303.  
  304.   /* In append, if all but last arg are nil, return last arg */
  305.   if (target_type == Lisp_Cons && EQ (val, Qnil))
  306.     return last_tail;
  307.  
  308.   if (CONSP (val))
  309.     tail = val, toindex = -1;        /* -1 in toindex is flag we are making a list */
  310.   else
  311.     toindex = 0;
  312.  
  313.   prev = Qnil;
  314.  
  315.   for (argnum = 0; argnum < nargs; argnum++)
  316.     {
  317.       Lisp_Object thislen;
  318.       int thisleni;
  319.       register int thisindex = 0;
  320.  
  321.       this = args[argnum];
  322.       if (!CONSP (this))
  323.     thislen = Flength (this), thisleni = XINT (thislen);
  324.  
  325.       while (1)
  326.     {
  327.       register Lisp_Object elt;
  328.  
  329.       /* Fetch next element of `this' arg into `elt', or break if `this' is exhausted. */
  330.       if (NULL (this)) break;
  331.       if (CONSP (this))
  332.         elt = Fcar (this), this = Fcdr (this);
  333.       else
  334.         {
  335.           if (thisindex >= thisleni) break;
  336.           if (XTYPE (this) == Lisp_String)
  337.         XFASTINT (elt) = XSTRING (this)->data[thisindex++];
  338.           else
  339.         elt = XVECTOR (this)->contents[thisindex++];
  340.         }
  341.  
  342.       /* Store into result */
  343.       if (toindex < 0)
  344.         {
  345.           XCONS (tail)->car = elt;
  346.           prev = tail;
  347.           tail = XCONS (tail)->cdr;
  348.         }
  349.       else if (XTYPE (val) == Lisp_Vector)
  350.         XVECTOR (val)->contents[toindex++] = elt;
  351.       else
  352.         {
  353.           while (XTYPE (elt) != Lisp_Int)
  354.         elt = wrong_type_argument (Qintegerp, elt);
  355.           {
  356. #ifdef MASSC_REGISTER_BUG
  357.         /* Even removing all "register"s doesn't disable this bug!
  358.            Nothing simpler than this seems to work. */
  359.         unsigned char *p = & XSTRING (val)->data[toindex++];
  360.         *p = XINT (elt);
  361. #else
  362.         XSTRING (val)->data[toindex++] = XINT (elt);
  363. #endif
  364.           }
  365.         }
  366.     }
  367.     }
  368.   if (!NULL (prev))
  369.     XCONS (prev)->cdr = last_tail;
  370.  
  371.   return val;  
  372. }
  373.  
  374. DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
  375.   "Return a copy of ALIST.\n\
  376. This is a new alist which represents the same mapping\n\
  377. from objects to objects, but does not share the alist structure with ALIST.\n\
  378. The objects mapped (cars and cdrs of elements of the alist)\n\
  379. are shared, however.")
  380.   (alist)
  381.      Lisp_Object alist;
  382. {
  383.   register Lisp_Object tem;
  384.  
  385.   CHECK_LIST (alist, 0);
  386.   if (NULL (alist))
  387.     return alist;
  388.   alist = concat (1, &alist, Lisp_Cons, 0);
  389.   for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
  390.     {
  391.       register Lisp_Object car;
  392.       car = XCONS (tem)->car;
  393.  
  394.       if (CONSP (car))
  395.     XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
  396.     }
  397.   return alist;
  398. }
  399.  
  400. DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
  401.   "Return a substring of STRING, starting at index FROM and ending before TO.\n\
  402. TO may be nil or omitted; then the substring runs to the end of STRING.\n\
  403. If FROM or TO is negative, it counts from the end.")
  404.   (string, from, to)
  405.      Lisp_Object string;
  406.      register Lisp_Object from, to;
  407. {
  408.   CHECK_STRING (string, 0);
  409.   CHECK_NUMBER (from, 1);
  410.   if (NULL (to))
  411.     to = Flength (string);
  412.   else
  413.     CHECK_NUMBER (to, 2);
  414.  
  415.   if (XINT (from) < 0)
  416.     XSETINT (from, XINT (from) + XSTRING (string)->size);
  417.   if (XINT (to) < 0)
  418.     XSETINT (to, XINT (to) + XSTRING (string)->size);
  419.   if (!(0 <= XINT (from) && XINT (from) <= XINT (to)
  420.         && XINT (to) <= XSTRING (string)->size))
  421.     args_out_of_range_3 (string, from, to);
  422.  
  423.   return make_string (XSTRING (string)->data + XINT (from),
  424.               XINT (to) - XINT (from));
  425. }
  426.  
  427. DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
  428.   "Takes cdr N times on LIST, returns the result.")
  429.   (n, list)
  430.      Lisp_Object n;
  431.      register Lisp_Object list;
  432. {
  433.   register int i, num;
  434.   CHECK_NUMBER (n, 0);
  435.   num = XINT (n);
  436.   for (i = 0; i < num && !NULL (list); i++)
  437.     {
  438.       QUIT;
  439.       list = Fcdr (list);
  440.     }
  441.   return list;
  442. }
  443.  
  444. DEFUN ("nth", Fnth, Snth, 2, 2, 0,
  445.   "Returns the Nth element of LIST.\n\
  446. N counts from zero.  If LIST is not that long, nil is returned.")
  447.   (n, list)
  448.      Lisp_Object n, list;
  449. {
  450.   return Fcar (Fnthcdr (n, list));
  451. }
  452.  
  453. DEFUN ("elt", Felt, Selt, 2, 2, 0,
  454.   "Returns element of SEQUENCE at index N.")
  455.   (seq, n)
  456.      register Lisp_Object seq, n;
  457. {
  458.   CHECK_NUMBER (n, 0);
  459.   while (1)
  460.     {
  461.       if (XTYPE (seq) == Lisp_Cons || NULL (seq))
  462.     return Fcar (Fnthcdr (n, seq));
  463.       else if (XTYPE (seq) == Lisp_String ||
  464.            XTYPE (seq) == Lisp_Vector)
  465.     return Faref (seq, n);
  466.       else
  467.     seq = wrong_type_argument (Qsequencep, seq);
  468.     }
  469. }
  470.  
  471. DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
  472.   "Returns non-nil if ELT is an element of LIST.  Comparison done with EQ.\n\
  473. The value is actually the tail of LIST whose car is ELT.")
  474.   (elt, list)
  475.      register Lisp_Object elt;
  476.      Lisp_Object list;
  477. {
  478.   register Lisp_Object tail;
  479.   for (tail = list; !NULL (tail); tail = Fcdr (tail))
  480.     {
  481.       register Lisp_Object tem;
  482.       tem = Fcar (tail);
  483.       if (EQ (elt, tem)) return tail;
  484.       QUIT;
  485.     }
  486.   return Qnil;
  487. }
  488.  
  489. DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
  490.   "Returns non-nil if ELT is the car of an element of LIST.  Comparison done with eq.\n\
  491. The value is actually the element of LIST whose car is ELT.")
  492.   (key, list)
  493.      register Lisp_Object key;
  494.      Lisp_Object list;
  495. {
  496.   register Lisp_Object tail;
  497.   for (tail = list; !NULL (tail); tail = Fcdr (tail))
  498.     {
  499.       register Lisp_Object elt, tem;
  500.       elt = Fcar (tail);
  501.       if (!CONSP (elt)) continue;
  502.       tem = Fcar (elt);
  503.       if (EQ (key, tem)) return elt;
  504.       QUIT;
  505.     }
  506.   return Qnil;
  507. }
  508.  
  509. /* Like Fassq but never report an error and do not allow quits.
  510.    Use only on lists known never to be circular.  */
  511.  
  512. Lisp_Object
  513. assq_no_quit (key, list)
  514.      register Lisp_Object key;
  515.      Lisp_Object list;
  516. {
  517.   register Lisp_Object tail;
  518.   for (tail = list; CONSP (tail); tail = Fcdr (tail))
  519.     {
  520.       register Lisp_Object elt, tem;
  521.       elt = Fcar (tail);
  522.       if (!CONSP (elt)) continue;
  523.       tem = Fcar (elt);
  524.       if (EQ (key, tem)) return elt;
  525.     }
  526.   return Qnil;
  527. }
  528.  
  529. DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
  530.   "Returns non-nil if ELT is the car of an element of LIST.  Comparison done with  equal.\n\
  531. The value is actually the element of LIST whose car is ELT.")
  532.   (key, list)
  533.      register Lisp_Object key;
  534.      Lisp_Object list;
  535. {
  536.   register Lisp_Object tail;
  537.   for (tail = list; !NULL (tail); tail = Fcdr (tail))
  538.     {
  539.       register Lisp_Object elt, tem;
  540.       elt = Fcar (tail);
  541.       if (!CONSP (elt)) continue;
  542.       tem = Fequal (Fcar (elt), key);
  543.       if (!NULL (tem)) return elt;
  544.       QUIT;
  545.     }
  546.   return Qnil;
  547. }
  548.  
  549. DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
  550.   "Returns non-nil if ELT is the cdr of an element of LIST.  Comparison done with EQ.\n\
  551. The value is actually the element of LIST whose cdr is ELT.")
  552.   (key, list)
  553.      register Lisp_Object key;
  554.      Lisp_Object list;
  555. {
  556.   register Lisp_Object tail;
  557.   for (tail = list; !NULL (tail); tail = Fcdr (tail))
  558.     {
  559.       register Lisp_Object elt, tem;
  560.       elt = Fcar (tail);
  561.       if (!CONSP (elt)) continue;
  562.       tem = Fcdr (elt);
  563.       if (EQ (key, tem)) return elt;
  564.       QUIT;
  565.     }
  566.   return Qnil;
  567. }
  568.  
  569. DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
  570.   "Deletes by side effect any occurrences of ELT as a member of LIST.\n\
  571. The modified LIST is returned.\n\
  572. If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
  573. therefore, write  (setq foo (delq element foo))  to be sure of changing  foo.")
  574.   (elt, list)
  575.      register Lisp_Object elt;
  576.      Lisp_Object list;
  577. {
  578.   register Lisp_Object tail, prev;
  579.   register Lisp_Object tem;
  580.  
  581.   tail = list;
  582.   prev = Qnil;
  583.   while (!NULL (tail))
  584.     {
  585.       tem = Fcar (tail);
  586.       if (EQ (elt, tem))
  587.     {
  588.       if (NULL (prev))
  589.         list = Fcdr (tail);
  590.       else
  591.         Fsetcdr (prev, Fcdr (tail));
  592.     }
  593.       else
  594.     prev = tail;
  595.       tail = Fcdr (tail);
  596.       QUIT;
  597.     }
  598.   return list;
  599. }
  600.  
  601. DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
  602.   "Reverses LIST by modifying cdr pointers.  Returns the beginning of the reversed list.")
  603.   (list)
  604.      Lisp_Object list;
  605. {
  606.   register Lisp_Object prev, tail, next;
  607.  
  608.   if (NULL (list)) return list;
  609.   prev = Qnil;
  610.   tail = list;
  611.   while (!NULL (tail))
  612.     {
  613.       QUIT;
  614.       next = Fcdr (tail);
  615.       Fsetcdr (tail, prev);
  616.       prev = tail;
  617.       tail = next;
  618.     }
  619.   return prev;
  620. }
  621.  
  622. DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
  623.   "Reverses LIST, copying.  Returns the beginning of the reversed list.\n\
  624. See also the function  nreverse, which is used more often.")
  625.   (list)
  626.      Lisp_Object list;
  627. {
  628.   Lisp_Object length;
  629.   register Lisp_Object *vec;
  630.   register Lisp_Object tail;
  631.   register int i;
  632.  
  633.   length = Flength (list);
  634.   vec = (Lisp_Object *) alloca (XINT (length) * sizeof (Lisp_Object));
  635.   for (i = XINT (length) - 1, tail = list; i >= 0; i--, tail = Fcdr (tail))
  636.     vec[i] = Fcar (tail);
  637.  
  638.   return Flist (XINT (length), vec);
  639. }
  640.  
  641. Lisp_Object merge ();
  642.  
  643. DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
  644.   "Sort LIST, stably, comparing elements using PREDICATE.\n\
  645. Returns the sorted list.  LIST is modified by side effects.\n\
  646. PREDICATE is called with two elements of LIST, and should return T\n\
  647. if the first element is \"less\" than the second.")
  648.   (list, pred)
  649.      Lisp_Object list, pred;
  650. {
  651.   Lisp_Object front, back;
  652.   register Lisp_Object len, tem;
  653.   struct gcpro gcpro1, gcpro2;
  654.   register int length;
  655.  
  656.   front = list;
  657.   len = Flength (list);
  658.   length = XINT (len);
  659.   if (length < 2)
  660.     return list;
  661.  
  662.   XSETINT (len, (length / 2) - 1);
  663.   tem = Fnthcdr (len, list);
  664.   back = Fcdr (tem);
  665.   Fsetcdr (tem, Qnil);
  666.  
  667.   GCPRO2 (front, back);
  668.   front = Fsort (front, pred);
  669.   back = Fsort (back, pred);
  670.   UNGCPRO;
  671.   return merge (front, back, pred);
  672. }
  673.  
  674. Lisp_Object
  675. merge (org_l1, org_l2, pred)
  676.      Lisp_Object org_l1, org_l2;
  677.      Lisp_Object pred;
  678. {
  679.   Lisp_Object value;
  680.   register Lisp_Object tail;
  681.   Lisp_Object tem;
  682.   register Lisp_Object l1, l2;
  683.   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
  684.  
  685.   l1 = org_l1;
  686.   l2 = org_l2;
  687.   tail = Qnil;
  688.   value = Qnil;
  689.  
  690.   /* It is sufficient to protect org_l1 and org_l2.
  691.      When l1 and l2 are updated, we copy the new values
  692.      back into the org_ vars.  */
  693.   GCPRO4 (org_l1, org_l2, pred, value);
  694.  
  695.   while (1)
  696.     {
  697.       if (NULL (l1))
  698.     {
  699.       UNGCPRO;
  700.       if (NULL (tail))
  701.         return l2;
  702.       Fsetcdr (tail, l2);
  703.       return value;
  704.     }
  705.       if (NULL (l2))
  706.     {
  707.       UNGCPRO;
  708.       if (NULL (tail))
  709.         return l1;
  710.       Fsetcdr (tail, l1);
  711.       return value;
  712.     }
  713.       tem = call2 (pred, Fcar (l2), Fcar (l1));
  714.       if (NULL (tem))
  715.     {
  716.       tem = l1;
  717.       l1 = Fcdr (l1);
  718.       org_l1 = l1;
  719.     }
  720.       else
  721.     {
  722.       tem = l2;
  723.       l2 = Fcdr (l2);
  724.       org_l2 = l2;
  725.     }
  726.       if (NULL (tail))
  727.     value = tem;
  728.       else
  729.     Fsetcdr (tail, tem);
  730.       tail = tem;
  731.     }
  732. }
  733.  
  734. DEFUN ("get", Fget, Sget, 2, 2, 0,
  735.   "Return the value of SYMBOL's PROPNAME property.\n\
  736. This is the last VALUE stored with  (put SYMBOL PROPNAME VALUE).")
  737.   (sym, prop)
  738.      Lisp_Object sym;
  739.      register Lisp_Object prop;
  740. {
  741.   register Lisp_Object tail;
  742.   for (tail = Fsymbol_plist (sym); !NULL (tail); tail = Fcdr (Fcdr (tail)))
  743.     {
  744.       register Lisp_Object tem;
  745.       tem = Fcar (tail);
  746.       if (EQ (prop, tem))
  747.     return Fcar (Fcdr (tail));
  748.     }
  749.   return Qnil;
  750. }
  751.  
  752. DEFUN ("put", Fput, Sput, 3, 3, 0,
  753.   "Store SYMBOL's PROPNAME property with value VALUE.\n\
  754. It can be retrieved with  (get SYMBOL PROPNAME).")
  755.   (sym, prop, val)
  756.      Lisp_Object sym;
  757.      register Lisp_Object prop;
  758.      Lisp_Object val;
  759. {
  760.   register Lisp_Object tail, prev;
  761.   Lisp_Object newcell;
  762.   prev = Qnil;
  763.   for (tail = Fsymbol_plist (sym); !NULL (tail); tail = Fcdr (Fcdr (tail)))
  764.     {
  765.       register Lisp_Object tem;
  766.       tem = Fcar (tail);
  767.       if (EQ (prop, tem))
  768.     return Fsetcar (Fcdr (tail), val);
  769.       prev = tail;
  770.     }
  771.   newcell = Fcons (prop, Fcons (val, Qnil));
  772.   if (NULL (prev))
  773.     Fsetplist (sym, newcell);
  774.   else
  775.     Fsetcdr (Fcdr (prev), newcell);
  776.   return val;
  777. }
  778.  
  779. DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
  780.   "T if two Lisp objects have similar structure and contents.\n\
  781. They must have the same data type.\n\
  782. Conses are compared by comparing the cars and the cdrs.\n\
  783. Vectors and strings are compared element by element.\n\
  784. Numbers are compared by value.  Symbols must match exactly.")
  785.   (o1, o2)
  786.      register Lisp_Object o1, o2;
  787. {
  788. do_cdr:
  789.   QUIT;
  790.   if (XTYPE (o1) != XTYPE (o2)) return Qnil;
  791.   if (XINT (o1) == XINT (o2)) return Qt;
  792.   if (XTYPE (o1) == Lisp_Cons)
  793.     {
  794.       Lisp_Object v1;
  795.       v1 = Fequal (Fcar (o1), Fcar (o2));
  796.       if (NULL (v1))
  797.     return v1;
  798.       o1 = Fcdr (o1), o2 = Fcdr (o2);
  799.       goto do_cdr;
  800.     }
  801.   if (XTYPE (o1) == Lisp_Marker)
  802.     {
  803.       return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
  804.           && XMARKER (o1)->bufpos == XMARKER (o2)->bufpos)
  805.     ? Qt : Qnil;
  806.     }
  807.   if (XTYPE (o1) == Lisp_Vector)
  808.     {
  809.       register int index;
  810.       if (XVECTOR (o1)->size != XVECTOR (o2)->size)
  811.     return Qnil;
  812.       for (index = 0; index < XVECTOR (o1)->size; index++)
  813.     {
  814.       Lisp_Object v, v1, v2;
  815.       v1 = XVECTOR (o1)->contents [index];
  816.       v2 = XVECTOR (o2)->contents [index];
  817.       v = Fequal (v1, v2);
  818.       if (NULL (v)) return v;
  819.     }
  820.       return Qt;
  821.     }
  822.   if (XTYPE (o1) == Lisp_String)
  823.     {
  824.       if (XSTRING (o1)->size != XSTRING (o2)->size)
  825.     return Qnil;
  826.       if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data, XSTRING (o1)->size))
  827.     return Qnil;
  828.       return Qt;
  829.     }
  830.   return Qnil;
  831. }
  832.  
  833. DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
  834.   "Store each element of ARRAY with ITEM.  ARRAY is a vector or string.")
  835.   (array, item)
  836.      Lisp_Object array, item;
  837. {
  838.   register int size, index, charval;
  839.  retry:
  840.   if (XTYPE (array) == Lisp_Vector)
  841.     {
  842.       register Lisp_Object *p = XVECTOR (array)->contents;
  843.       size = XVECTOR (array)->size;
  844.       for (index = 0; index < size; index++)
  845.     p[index] = item;
  846.     }
  847.   else if (XTYPE (array) == Lisp_String)
  848.     {
  849.       register unsigned char *p = XSTRING (array)->data;
  850.       CHECK_NUMBER (item, 1);
  851.       charval = XINT (item);
  852.       size = XSTRING (array)->size;
  853.       for (index = 0; index < size; index++)
  854.     p[index] = charval;
  855.     }
  856.   else
  857.     {
  858.       array = wrong_type_argument (Qarrayp, array);
  859.       goto retry;
  860.     }
  861.   return array;
  862. }
  863.  
  864. /* ARGSUSED */
  865. Lisp_Object
  866. nconc2 (s1, s2)
  867.      Lisp_Object s1, s2;
  868. {
  869. #ifdef NO_ARG_ARRAY
  870.   Lisp_Object args[2];
  871.   args[0] = s1;
  872.   args[1] = s2;
  873.   return Fnconc (2, args);
  874. #else
  875.   return Fnconc (2, &s1);
  876. #endif /* NO_ARG_ARRAY */
  877. }
  878.  
  879. DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
  880.   "Concatenate any number of lists by altering them.\n\
  881. Only the last argument is not altered, and need not be a list.")
  882.   (nargs, args)
  883.      int nargs;
  884.      Lisp_Object *args;
  885. {
  886.   register int argnum;
  887.   register Lisp_Object tail, tem, val;
  888.  
  889.   val = Qnil;
  890.  
  891.   for (argnum = 0; argnum < nargs; argnum++)
  892.     {
  893.       tem = args[argnum];
  894.       if (NULL (tem)) continue;
  895.  
  896.       if (NULL (val))
  897.     val = tem;
  898.  
  899.       if (argnum + 1 == nargs) break;
  900.  
  901.       if (!CONSP (tem))
  902.     tem = wrong_type_argument (Qlistp, tem);
  903.  
  904.       while (CONSP (tem))
  905.     {
  906.       tail = tem;
  907.       tem = Fcdr (tail);
  908.       QUIT;
  909.     }
  910.  
  911.       tem = args[argnum + 1];
  912.       Fsetcdr (tail, tem);
  913.       if (NULL (tem))
  914.     args[argnum + 1] = tail;
  915.     }
  916.  
  917.   return val;
  918. }
  919.  
  920. /* This is the guts of all mapping functions.
  921.  Apply fn to each element of seq, one by one,
  922.  storing the results into elements of vals, a C vector of Lisp_Objects.
  923.  leni is the length of vals, which should also be the length of seq. */
  924.  
  925. static void
  926. mapcar1 (leni, vals, fn, seq)
  927.      int leni;
  928.      Lisp_Object *vals;
  929.      Lisp_Object fn, seq;
  930. {
  931.   register Lisp_Object tail;
  932.   Lisp_Object dummy;
  933.   register int i;
  934.   struct gcpro gcpro1, gcpro2, gcpro3;
  935.  
  936.   /* Don't let vals contain any garbage when GC happens.  */
  937.   for (i = 0; i < leni; i++)
  938.     vals[i] = Qnil;
  939.  
  940.   GCPRO3 (dummy, fn, seq);
  941.   gcpro1.var = vals;
  942.   gcpro1.nvars = leni;
  943.   /* We need not explicitly protect `tail' because it is used only on lists, and
  944.     1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
  945.  
  946.   if (XTYPE (seq) == Lisp_Vector)
  947.     {
  948.       for (i = 0; i < leni; i++)
  949.     {
  950.       dummy = XVECTOR (seq)->contents[i];
  951.       vals[i] = call1 (fn, dummy);
  952.     }
  953.     }
  954.   else if (XTYPE (seq) == Lisp_String)
  955.     {
  956.       for (i = 0; i < leni; i++)
  957.     {
  958.       XFASTINT (dummy) = XSTRING (seq)->data[i];
  959.       vals[i] = call1 (fn, dummy);
  960.     }
  961.     }
  962.   else   /* Must be a list, since Flength did not get an error */
  963.     {
  964.       tail = seq;
  965.       for (i = 0; i < leni; i++)
  966.     {
  967.       vals[i] = call1 (fn, Fcar (tail));
  968.       tail = Fcdr (tail);
  969.     }
  970.     }
  971.  
  972.   UNGCPRO;
  973. }
  974.  
  975. DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
  976.   "Apply FN to each element of SEQ, and concat the results as strings.\n\
  977. In between each pair of results, stick in SEP.\n\
  978. Thus, \" \" as SEP results in spaces between the values return by FN.")
  979.   (fn, seq, sep)
  980.      Lisp_Object fn, seq, sep;
  981. {
  982.   Lisp_Object len;
  983.   register int leni;
  984.   int nargs;
  985.   register Lisp_Object *args;
  986.   register int i;
  987.   int j;
  988.   struct gcpro gcpro1;
  989.  
  990.   len = Flength (seq);
  991.   leni = XINT (len);
  992.   nargs = leni + leni - 1;
  993.   if (nargs < 0) return build_string ("");
  994.  
  995.   args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
  996.  
  997.   GCPRO1 (sep);
  998.   mapcar1 (leni, args, fn, seq);
  999.   UNGCPRO;
  1000.  
  1001.   /* Broken Xenix/386 compiler can't use a register variable here */
  1002.   for (j = leni - 1; j > 0; j--)
  1003.     args[j + j] = args[j];
  1004.  
  1005.   for (i = 1; i < nargs; i += 2)
  1006.     args[i] = sep;
  1007.  
  1008.   return Fconcat (nargs, args);
  1009. }
  1010.  
  1011. DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
  1012.   "Apply FUNCTION to each element of LIST, and make a list of the results.\n\
  1013. The result is a list just as long as LIST.")
  1014.   (fn, seq)
  1015.      Lisp_Object fn, seq;
  1016. {
  1017.   register Lisp_Object len;
  1018.   register int leni;
  1019.   register Lisp_Object *args;
  1020.  
  1021.   len = Flength (seq);
  1022.   leni = XFASTINT (len);
  1023.   args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
  1024.  
  1025.   mapcar1 (leni, args, fn, seq);
  1026.  
  1027.   return Flist (leni, args);
  1028. }
  1029.  
  1030. /* Anything that calls this function must protect from GC!  */
  1031.  
  1032. DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
  1033.   "Ask user a \"y or n\" question.  Return t if answer is \"y\".\n\
  1034. Takes one argument, which is the string to display to ask the question.\n\
  1035. It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
  1036. No confirmation of the answer is requested; a single character is enough.\n\
  1037. Also accepts Space to mean yes, or Delete to mean no.")
  1038.   (prompt)
  1039.      Lisp_Object prompt;
  1040. {
  1041.   register int ans;
  1042.   Lisp_Object xprompt;
  1043.   Lisp_Object args[2];
  1044.   int ocech = cursor_in_echo_area;
  1045.   struct gcpro gcpro1, gcpro2;
  1046.  
  1047.   CHECK_STRING (prompt, 0);
  1048.   xprompt = prompt;
  1049.   GCPRO2 (prompt, xprompt);
  1050.  
  1051.   while (1)
  1052.     {
  1053.       message ("%s(y or n) ", XSTRING (xprompt)->data);
  1054.       cursor_in_echo_area = 1;
  1055.       ans = read_command_char (0);
  1056.       cursor_in_echo_area = -1;
  1057.       message ("%s(y or n) %c", XSTRING (xprompt)->data, ans);
  1058.       cursor_in_echo_area = ocech;
  1059.       QUIT;
  1060.       if (ans >= 0)
  1061.     ans = DOWNCASE (ans);
  1062.       if (ans == 'y' || ans == ' ')
  1063.     { ans = 'y'; break; }
  1064.       if (ans == 'n' || ans == 127)
  1065.     break;
  1066.  
  1067.       Fding (Qnil);
  1068.       Fdiscard_input ();
  1069.       if (EQ (xprompt, prompt))
  1070.     {
  1071.       args[0] = build_string ("Please answer y or n.  ");
  1072.       args[1] = prompt;
  1073.       xprompt = Fconcat (2, args);
  1074.     }
  1075.     }
  1076.   UNGCPRO;
  1077.   return (ans == 'y' ? Qt : Qnil);
  1078. }
  1079.  
  1080. /* Anything that calls this function must protect from GC!  */
  1081.  
  1082. DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
  1083.   "Ask user a yes-or-no question.  Return t if answer is yes.\n\
  1084. Takes one argument, which is the string to display to ask the question.\n\
  1085. It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
  1086. The user must confirm the answer with RET,\n\
  1087. and can edit it until it as been confirmed.")
  1088.   (prompt)
  1089.      Lisp_Object prompt;
  1090. {
  1091.   register Lisp_Object ans;
  1092.   Lisp_Object args[2];
  1093.   struct gcpro gcpro1;
  1094.  
  1095.   CHECK_STRING (prompt, 0);
  1096.  
  1097.   args[0] = prompt;
  1098.   args[1] = build_string ("(yes or no) ");
  1099.   prompt = Fconcat (2, args);
  1100.  
  1101.   GCPRO1 (prompt);
  1102.   while (1)
  1103.     {
  1104.       ans = Fdowncase (read_minibuf (Vminibuffer_local_map,
  1105.                      Qnil, prompt, 0));
  1106.       if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
  1107.     {
  1108.       UNGCPRO;
  1109.       return Qt;
  1110.     }
  1111.       if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
  1112.     {
  1113.       UNGCPRO;
  1114.       return Qnil;
  1115.     }
  1116.  
  1117.       Fding (Qnil);
  1118.       Fdiscard_input ();
  1119.       message ("Please answer yes or no.");
  1120.       Fsleep_for (make_number (2));
  1121.     }
  1122. }
  1123.  
  1124. /* Avoid static vars inside a function since in HPUX they dump as pure.  */
  1125. #ifdef DGUX
  1126. static struct dg_sys_info_load_info load_info;  /* what-a-mouthful! */
  1127.  
  1128. #else /* Not DGUX */
  1129.  
  1130. static int ldav_initialized;
  1131. static int ldav_channel;
  1132. #ifdef LOAD_AVE_TYPE
  1133. #ifndef VMS
  1134. static struct nlist ldav_nl[2];
  1135. #endif /* VMS */
  1136. #endif /* LOAD_AVE_TYPE */
  1137.  
  1138. #define channel ldav_channel
  1139. #define initialized ldav_initialized
  1140. #define nl ldav_nl
  1141. #endif /* Not DGUX */
  1142.  
  1143. DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0,
  1144.   "Return the current 1 minute, 5 minute and 15 minute load averages\n\
  1145. in a list (all floating point load average values are multiplied by 100\n\
  1146. and then turned into integers).")
  1147.   ()
  1148. {
  1149. #ifdef DGUX
  1150.   /* perhaps there should be a "sys_load_avg" call in sysdep.c?! - DJB */
  1151.   load_info.one_minute     = 0.0;    /* just in case there is an error */
  1152.   load_info.five_minute    = 0.0;
  1153.   load_info.fifteen_minute = 0.0;
  1154.   dg_sys_info (&load_info, DG_SYS_INFO_LOAD_INFO_TYPE,
  1155.            DG_SYS_INFO_LOAD_VERSION_0);
  1156.  
  1157.   return Fcons (make_number ((int)(load_info.one_minute * 100.0)),
  1158.         Fcons (make_number ((int)(load_info.five_minute * 100.0)),
  1159.                Fcons (make_number ((int)(load_info.fifteen_minute * 100.0)),
  1160.                   Qnil)));
  1161. #else /* not DGUX */
  1162. #ifndef LOAD_AVE_TYPE
  1163.   error ("load-average not implemented for this operating system");
  1164.  
  1165. #else /* LOAD_AVE_TYPE defined */
  1166.  
  1167.   LOAD_AVE_TYPE load_ave[3];
  1168. #ifdef VMS
  1169. #ifndef eunice
  1170. #include <iodef.h>
  1171. #include <descrip.h>
  1172. #else
  1173. #include <vms/iodef.h>
  1174.   struct {int dsc$w_length; char *dsc$a_pointer;} descriptor;
  1175. #endif /* eunice */
  1176. #endif /* VMS */
  1177.  
  1178.   /* If this fails for any reason, we can return (0 0 0) */
  1179.   load_ave[0] = 0.0; load_ave[1] = 0.0; load_ave[2] = 0.0;
  1180.  
  1181. #ifdef VMS
  1182.   /*
  1183.    *    VMS specific code -- read from the Load Ave driver
  1184.    */
  1185.  
  1186.   /*
  1187.    *    Ensure that there is a channel open to the load ave device
  1188.    */
  1189.   if (initialized == 0)
  1190.     {
  1191.       /* Attempt to open the channel */
  1192. #ifdef eunice
  1193.       descriptor.size = 18;
  1194.       descriptor.ptr  = "$$VMS_LOAD_AVERAGE";
  1195. #else
  1196.       $DESCRIPTOR(descriptor, "LAV0:");
  1197. #endif
  1198.       if (sys$assign (&descriptor, &channel, 0, 0) & 1)
  1199.     initialized = 1;
  1200.     }
  1201.   /*
  1202.    *    Read the load average vector
  1203.    */
  1204.   if (initialized)
  1205.     {
  1206.       if (!(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
  1207.              load_ave, 12, 0, 0, 0, 0)
  1208.         & 1))
  1209.     {
  1210.       sys$dassgn (channel);
  1211.       initialized = 0;
  1212.     }
  1213.     }
  1214. #else  /* not VMS */
  1215.   /*
  1216.    *    4.2BSD UNIX-specific code -- read _avenrun from /dev/kmem
  1217.    */
  1218.  
  1219.   /*
  1220.    *    Make sure we have the address of _avenrun
  1221.    */
  1222.   if (nl[0].n_value == 0)
  1223.     {
  1224.       /*
  1225.        *    Get the address of _avenrun
  1226.        */
  1227. #ifndef NLIST_STRUCT
  1228.       strcpy (nl[0].n_name, LDAV_SYMBOL);
  1229.       nl[1].n_zeroes = 0;
  1230. #else /* NLIST_STRUCT */
  1231. #if defined (convex) || defined (NeXT)
  1232.       nl[0].n_un.n_name = LDAV_SYMBOL;
  1233.       nl[1].n_un.n_name = 0;
  1234. #else /* not convex or NeXT */
  1235.       nl[0].n_name = LDAV_SYMBOL;
  1236.       nl[1].n_name = 0;
  1237. #endif /* not convex of NeXT */
  1238. #endif /* NLIST_STRUCT */
  1239.  
  1240. #ifdef IRIS_4D
  1241.     {
  1242. #include <sys/types.h>
  1243. #include <sys/sysmp.h>
  1244.         nl[0].n_value = sysmp(MP_KERNADDR, MPKA_AVENRUN);
  1245.         nl[0].n_value &= 0x7fffffff;
  1246.     }
  1247. #else
  1248.       nlist (KERNEL_FILE, nl);
  1249. #endif /* IRIS */
  1250.  
  1251. #ifdef FIXUP_KERNEL_SYMBOL_ADDR
  1252.       if ((nl[0].n_type & N_TYPE) != N_ABS)
  1253.     nl[0].n_value = (nlp->n_value >> 2) | 0xc0000000;
  1254. #endif /* FIXUP_KERNEL_SYMBOL_ADDR */
  1255.     }
  1256.   /*
  1257.    *    Make sure we have /dev/kmem open
  1258.    */
  1259.   if (initialized == 0)
  1260.     {
  1261.       /*
  1262.        *    Open /dev/kmem
  1263.        */
  1264.       channel = open ("/dev/kmem", 0);
  1265.       if (channel >= 0) initialized = 1;
  1266.     }
  1267.   /*
  1268.    *    If we can, get the load ave values
  1269.    */
  1270.   if ((nl[0].n_value != 0) && (initialized != 0))
  1271.     {
  1272.       /*
  1273.        *    Seek to the correct address
  1274.        */
  1275.       lseek (channel, (long) nl[0].n_value, 0);
  1276.       if (read (channel, load_ave, sizeof load_ave)
  1277.       != sizeof(load_ave))
  1278.     {
  1279.       close (channel);
  1280.       initialized = 0;
  1281.     }
  1282.     }
  1283. #endif /* not VMS */
  1284.  
  1285.   /*
  1286.    *    Return the list of load average values
  1287.    */
  1288.   return Fcons (make_number (LOAD_AVE_CVT (load_ave[0])),
  1289.         Fcons (make_number (LOAD_AVE_CVT (load_ave[1])),
  1290.                Fcons (make_number (LOAD_AVE_CVT (load_ave[2])),
  1291.                   Qnil)));
  1292. #endif /* LOAD_AVE_TYPE */
  1293. #endif /* not DGUX */
  1294. }
  1295.  
  1296. #undef channel
  1297. #undef initialized
  1298. #undef nl
  1299.  
  1300. Lisp_Object Vfeatures;
  1301.  
  1302. DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
  1303.   "Returns t if FEATURE is present in this Emacs.\n\
  1304. Use this to conditionalize execution of lisp code based on the presence or\n\
  1305. absence of emacs or environment extensions.\n\
  1306. Use  provide  to declare that a feature is available.\n\
  1307. This function looks at the value of the variable  features.")
  1308.      (feature)
  1309.      Lisp_Object feature;
  1310. {
  1311.   register Lisp_Object tem;
  1312.   CHECK_SYMBOL (feature, 0);
  1313.   tem = Fmemq (feature, Vfeatures);
  1314.   return (NULL (tem)) ? Qnil : Qt;
  1315. }
  1316.  
  1317. DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
  1318.   "Announce that FEATURE is a feature of the current Emacs.")
  1319.      (feature)
  1320.      Lisp_Object feature;
  1321. {
  1322.   register Lisp_Object tem;
  1323.   CHECK_SYMBOL (feature, 0);
  1324.   if (!NULL (Vautoload_queue))
  1325.     Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
  1326.   tem = Fmemq (feature, Vfeatures);
  1327.   if (NULL (tem))
  1328.     Vfeatures = Fcons (feature, Vfeatures);
  1329.   return feature;
  1330. }
  1331.  
  1332. DEFUN ("require", Frequire, Srequire, 1, 2, 0,
  1333.   "If FEATURE is not present in Emacs (ie (featurep FEATURE) is false),\n\
  1334. load FILENAME.  FILENAME is optional and defaults to FEATURE.")
  1335.      (feature, file_name)
  1336.      Lisp_Object feature, file_name;
  1337. {
  1338.   register Lisp_Object tem;
  1339.   CHECK_SYMBOL (feature, 0);
  1340.   tem = Fmemq (feature, Vfeatures);
  1341.   if (NULL (tem))
  1342.     {
  1343.       int count = specpdl_ptr - specpdl;
  1344.  
  1345.       /* Value saved here is to be restored into Vautoload_queue */
  1346.       record_unwind_protect (un_autoload, Vautoload_queue);
  1347.       Vautoload_queue = Qt;
  1348.  
  1349.       Fload (NULL (file_name) ? Fsymbol_name (feature) : file_name,
  1350.          Qnil, Qt, Qnil);
  1351.  
  1352.       tem = Fmemq (feature, Vfeatures);
  1353.       if (NULL (tem))
  1354.     error ("Required feature %s was not provided",
  1355.            XSYMBOL (feature)->name->data );
  1356.  
  1357.       /* Once loading finishes, don't undo it.  */
  1358.       Vautoload_queue = Qt;
  1359.       unbind_to (count);
  1360.     }
  1361.   return feature;
  1362. }
  1363.  
  1364. syms_of_fns ()
  1365. {
  1366.   Qstring_lessp = intern ("string-lessp");
  1367.   staticpro (&Qstring_lessp);
  1368.  
  1369.   DEFVAR_LISP ("features", &Vfeatures,
  1370.     "A list of symbols which are the features of the executing emacs.\n\
  1371. Used by  featurep  and  require, and altered by  provide.");
  1372.   Vfeatures = Qnil;
  1373.  
  1374.   defsubr (&Sidentity);
  1375.   defsubr (&Srandom);
  1376.   defsubr (&Slength);
  1377.   defsubr (&Sstring_equal);
  1378.   defsubr (&Sstring_lessp);
  1379.   defsubr (&Sappend);
  1380.   defsubr (&Sconcat);
  1381.   defsubr (&Svconcat);
  1382.   defsubr (&Scopy_sequence);
  1383.   defsubr (&Scopy_alist);
  1384.   defsubr (&Ssubstring);
  1385.   defsubr (&Snthcdr);
  1386.   defsubr (&Snth);
  1387.   defsubr (&Selt);
  1388.   defsubr (&Smemq);
  1389.   defsubr (&Sassq);
  1390.   defsubr (&Sassoc);
  1391.   defsubr (&Srassq);
  1392.   defsubr (&Sdelq);
  1393.   defsubr (&Snreverse);
  1394.   defsubr (&Sreverse);
  1395.   defsubr (&Ssort);
  1396.   defsubr (&Sget);
  1397.   defsubr (&Sput);
  1398.   defsubr (&Sequal);
  1399.   defsubr (&Sfillarray);
  1400.   defsubr (&Snconc);
  1401.   defsubr (&Smapcar);
  1402.   defsubr (&Smapconcat);
  1403.   defsubr (&Sy_or_n_p);
  1404.   defsubr (&Syes_or_no_p);
  1405.   defsubr (&Sload_average);
  1406.   defsubr (&Sfeaturep);
  1407.   defsubr (&Srequire);
  1408.   defsubr (&Sprovide);
  1409. }
  1410.